add_library(scn_sanitizer_asan INTERFACE)
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
    set(ASAN_FLAG -g -fsanitize=address -fno-omit-frame-pointer)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    set(ASAN_FLAG /fsanitize=address)
else()
    set(ASAN_FLAG)
endif ()
target_compile_options(scn_sanitizer_asan INTERFACE ${ASAN_FLAG})
target_link_options(scn_sanitizer_asan INTERFACE ${ASAN_FLAG})

add_library(scn_sanitizer_ubsan INTERFACE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(UBSAN_FLAG -g -fsanitize=undefined)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(UBSAN_FLAG -g -fsanitize=undefined,float-divide-by-zero,local-bounds,vptr,nullability)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    set(UBSAN_FLAG /fsanitize=undefined)
else()
    set(UBSAN_FLAG)
endif ()
target_compile_options(scn_sanitizer_ubsan INTERFACE ${UBSAN_FLAG})
target_link_options(scn_sanitizer_ubsan INTERFACE ${UBSAN_FLAG})

add_library(scn_sanitizer_msan INTERFACE)
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
    set(MSAN_FLAG -g -fsanitize=memory)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    set(MSAN_FLAG /fsanitize=memory)
else()
    set(MSAN_FLAG)
endif ()
target_compile_options(scn_sanitizer_msan INTERFACE ${MSAN_FLAG})
target_link_options(scn_sanitizer_msan INTERFACE ${MSAN_FLAG})

add_library(scn_sanitizer_fuzzer INTERFACE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(FUZZER_FLAG -g -fsanitize=fuzzer -fno-omit-frame-pointer)
    target_compile_options(scn_sanitizer_fuzzer INTERFACE ${FUZZER_FLAG})
    target_link_options(scn_sanitizer_fuzzer INTERFACE ${FUZZER_FLAG})
endif()

add_library(scn_sanitizer_stackprotect INTERFACE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(STACKPROTECT_FLAG -g -fstack-protector-all -mshstk)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(STACKPROTECT_FLAG -g -fstack-protector-all -flto -fvisibility=hidden -fsanitize=cfi)
    if (SCN_USE_SAFESTACK)
        set(STACKPROTECT_FLAG ${STACKPROTECT_FLAG} -fsanitize=safe-stack)
    else()
        set(STACKPROTECT_FLAG ${STACKPROTECT_FLAG} -mshstk)
    endif()
else()
    set(STACKPROTECT_FLAG)
endif()
target_compile_options(scn_sanitizer_stackprotect INTERFACE ${STACKPROTECT_FLAG})
target_link_options(scn_sanitizer_stackprotect INTERFACE ${STACKPROTECT_FLAG})

add_library(scn_sanitizers INTERFACE)

if (SCN_USE_ASAN)
    target_link_libraries(scn_sanitizers INTERFACE scn_sanitizer_asan)
endif()
if (SCN_USE_UBSAN)
    target_link_libraries(scn_sanitizers INTERFACE scn_sanitizer_ubsan)
endif()
if (SCN_USE_MSAN)
    target_link_libraries(scn_sanitizers INTERFACE scn_sanitizer_msan)
endif()
if (SCN_USE_STACK_PROTECT)
    target_link_libraries(scn_sanitizers INTERFACE scn_sanitizer_stackprotect)
endif()

if (SCN_USE_ASAN OR SCN_USE_UBSAN OR SCN_USE_MSAN OR SCN_USE_STACK_PROTECT)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        target_compile_options(scn_sanitizers INTERFACE
                "-fsanitize-ignorelist=${CMAKE_CURRENT_LIST_DIR}/sanitizers-ignorelist.txt")
    endif()
endif()

if (SCN_FUZZING)
    add_library(scn_fuzzer INTERFACE)
    target_link_libraries(scn_fuzzer INTERFACE scn_sanitizers scn_sanitizer_fuzzer)
endif()
